﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using AfterlifeEditor.Forms;
using AfterlifeLib;
using AfterlifeLib.Levels;
using AfterlifeLib.Lighting;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using AfterlifeLib.Input;

namespace AfterlifeEditor
{
    public enum ToolState
    {
        PaintBrush,
        PaintBucket,
        Eraser,
        Collision,
        Light,
    }

    public partial class MainForm : Form
    {
        const int MIN_TILEDRAWSIZE = 16;
        const int MAX_TILEDRAWSIZE = 128;

        ContentManager contentManager;
        SpriteBatch spriteBatch;
        
        SpriteFont arialFont;

        Camera2D camera = new Camera2D(Vector2.Zero);

        Level CurrentLevel;

        Dictionary<string, TileLayer> tileLayerDict = new Dictionary<string, TileLayer>();
        TileLayer selectedTileLayer = null;
        
        Dictionary<string, CollisionLayer> collisionLayerDict = new Dictionary<string, CollisionLayer>();
        CollisionLayer selectedCollisionLayer = null;
        
        Dictionary<string, Light> lightsDict = new Dictionary<string, Light>();
        Light selectedLight = null;

        //If this is -1, we are editing the CollisionLayer or the lights
        int currentLayerIndex = 0;
        LayerType currentEditType = LayerType.Tile;

        ToolState toolState = ToolState.PaintBrush;

        Effect lightEffect;
        Effect combinedEffect;

        PresentationParameters pp;
        RenderTarget2D colorMapRenderTarget;
        RenderTarget2D shadowMapRenderTarget;
        Texture2D colorMapTexture;
        Texture2D shadowMapTexture;

        VertexDeclaration vertexDeclaration;
        VertexPositionTexture[] vertices = new VertexPositionTexture[]
        {
            new VertexPositionTexture(new Vector3(-1, 1, 0), new Vector2(0, 0)),
            new VertexPositionTexture(new Vector3(1, 1, 0), new Vector2(1, 0)),
            new VertexPositionTexture(new Vector3(-1, -1, 0), new Vector2(0, 1)),
            new VertexPositionTexture(new Vector3(1, -1, 0), new Vector2(1, 1)),
        };
        
        Texture2D emptyTile;
        Texture2D notWalkable;
        Texture2D tileMarker;

        bool mouseDown = false;

        int cellX = 0;
        int cellY = 0;
        int mx = 0;
        int my = 0;

        string AfterlifeLevelFileFilter = "Afterlife Level File (*.lvl)|*.lvl";
        string ImageFilesFilter = "Image Files (*.jpg;*.png;*.bmp;*.tga)|*.jpg;*.png;*.bmp;*.tga";
        string AllFilesFilter = "All Files (*.*)|*.*";

        public GraphicsDevice GraphicsDevice
        {
            get { return levelDisplay.GraphicsDevice; }
        }

        public MainForm()
        {
            InitializeComponent();
            
            contentManager = new ContentManager(levelDisplay.Services, Path.GetDirectoryName(Application.ExecutablePath));

            levelDisplay.OnInitialize += new EventHandler(levelDisplay_OnInitialize);
            levelDisplay.OnDraw += new EventHandler(levelDisplay_OnDraw);

            //Als we niks doen, blijf updaten en renderen
            Application.Idle += delegate { levelDisplay.Invalidate(); };

            //De muis coordinaten worden vanaf de levelDisplay gemeten
            Mouse.WindowHandle = levelDisplay.Handle;
        }

        void levelDisplay_OnInitialize(object sender, EventArgs e)
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);

            arialFont = contentManager.Load<SpriteFont>("Resources/Arial");

            lightEffect = contentManager.Load<Effect>("Resources/LightingShadow");
            combinedEffect = contentManager.Load<Effect>("Resources/LightingCombined");

            emptyTile = LoadTexture("Resources/empty.png");
            notWalkable = LoadTexture("Resources/notWalkable.png");
            tileMarker = LoadTexture("Resources/marker.png");

            vertexDeclaration = new VertexDeclaration(GraphicsDevice, VertexPositionTexture.VertexElements);

            InitializeRenderTargets();
        }

        private void InitializeRenderTargets()
        {
            pp = GraphicsDevice.PresentationParameters;
            int width = pp.BackBufferWidth;
            int height = pp.BackBufferHeight;
            SurfaceFormat format = pp.BackBufferFormat;
            colorMapRenderTarget = new RenderTarget2D(GraphicsDevice, width, height, 1, format);
            shadowMapRenderTarget = new RenderTarget2D(GraphicsDevice, width, height, 1, format);
        }

        private Texture2D LoadTexture(string path)
        {
            return Texture2D.FromFile(GraphicsDevice, path);
        }

        private void AdjustRenderTargets()
        {
            if (levelDisplay.Width <= 0 || levelDisplay.Height <= 0)
                return;

            colorMapRenderTarget = new RenderTarget2D(GraphicsDevice, levelDisplay.Width, levelDisplay.Height, 1, pp.BackBufferFormat);
            shadowMapRenderTarget = new RenderTarget2D(GraphicsDevice, levelDisplay.Width, levelDisplay.Height, 1, pp.BackBufferFormat);
        }

        public void AdjustScrollBars()
        {
            //Als we geen level geladen hebben, schakel de scrollBars uit
            if (CurrentLevel == null)
            {
                hScrollBar.Enabled = false;
                vScrollBar.Enabled = false;

                return;
            }

            //Als de breedte van het level meer is dan de levelDisplay, pas de scrollBars aan
            if (CurrentLevel.WidthInPixels > levelDisplay.Width)
            {
                hScrollBar.Minimum = 0;
                hScrollBar.Maximum = CurrentLevel.WidthInTiles;

                hScrollBar.Enabled = true;
            }
            else
            {
                hScrollBar.Enabled = false;
            }
            
            //Als de hoogte van het level meer is dan de levelDisplay, pas de scrollBars aan
            if (CurrentLevel.HeightInPixels > levelDisplay.Height)
            {
                vScrollBar.Minimum = 0;
                vScrollBar.Maximum = CurrentLevel.HeightInTiles;

                vScrollBar.Enabled = true;
            }
            else
            {
                vScrollBar.Enabled = false;
            }
        }

        //Als we de hScrollBar aanpassen, stel de camera opnieuw in
        private void hScrollBar_Scroll(object sender, ScrollEventArgs e)
        {
            camera.IntX = e.NewValue * Level.TileWidth;

            cameraToolStripStatusLabel.Text = string.Format("Camera: X:{0}, Y:{1}", camera.IntX, camera.IntY);
            levelDisplay.Invalidate();
        }

        //Als we de vScrollBar aanpassen, stel de camera opnieuw in
        private void vScrollBar_Scroll(object sender, ScrollEventArgs e)
        {
            camera.IntY = e.NewValue * Level.TileHeight;

            cameraToolStripStatusLabel.Text = string.Format("Camera: X:{0}, Y:{1}", camera.IntX, camera.IntY);
            levelDisplay.Invalidate();
        }

        void levelDisplay_OnDraw(object sender, EventArgs e)
        {
            Logic();
            Draw();
        }

        private void Logic()
        {
            InputState.Update();

            mx = InputState.MouseX;
            my = InputState.MouseY;

            //Als we een level geopend hebben
            if (CurrentLevel != null)
            {
                //Als de muis binnen de levelDisplay zit
                if (mx >= 0 && mx < levelDisplay.Width &&
                    my >= 0 && my < levelDisplay.Height)
                {
                    cellX = mx / Level.TileDrawWidth;
                    cellY = my / Level.TileDrawHeight;

                    cellToolStripStatusLabel.Text = string.Format("cellX: {0}, cellY: {1}", cellX, cellY);

                    cellX += camera.IntX / Level.TileDrawWidth;
                    cellY += camera.IntY / Level.TileDrawHeight;

                    if (cellX > CurrentLevel.WidthInTiles - 1)
                        cellX = -1;
                    if (cellY > CurrentLevel.HeightInTiles - 1)
                        cellY = -1;

                    //Als de muis ingedrukt is
                    if (mouseDown)
                    {
                        if (cellX == -1 || cellY == -1)
                            return;

                        int index = tileSelector1.SelectedIndex;

                        switch (toolState)
                        {
                            case ToolState.PaintBrush:
                                HandlePaintBrushTool(index);
                                break;
                            case ToolState.PaintBucket:
                                HandlePaintBucketTool(index);
                                break;
                            case ToolState.Eraser:
                                HandleEraserTool();
                                break;
                            case ToolState.Collision:
                                HandleCollisionTool();
                                break;
                            case ToolState.Light:
                                HandleLightTool();
                                break;
                        }
                    }
                }
                else
                {
                    cellX = -1;
                    cellY = -1;
                }
            }
        }

        private void HandlePaintBrushTool(int index)
        {
            if(index != -1 && selectedTileLayer != null)
            {
                selectedTileLayer[cellX, cellY] = index;
            }
        }

        private void HandlePaintBucketTool(int index)
        {
            if(index != -1 && selectedTileLayer != null)
            {
                selectedTileLayer.RecursiveFill(cellX, cellY, index);
            }
        }

        private void HandleEraserTool()
        {
            if (currentEditType == LayerType.Tile && selectedTileLayer != null)
            {
                selectedTileLayer[cellX, cellY] = -1;
            }
        }

        private void HandleCollisionTool()
        {
            if (currentEditType == LayerType.Collision && selectedCollisionLayer != null)
            {
                selectedCollisionLayer[cellX, cellY] = walkableToolStripCheckBox.CheckBox.Checked ? 1 : 0;
            }
        }

        private void HandleLightTool()
        {
            selectedLight.Position = new Vector3(mx - camera.IntX, my - camera.IntY, 0);
        }

        private void Draw()
        {
            GraphicsDevice.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);

            //Als we een level geladen hebben
            if (CurrentLevel == null)
                return;

            if (currentEditType == LayerType.Tile && currentLayerIndex < CurrentLevel.TileLayers.Length)
            {
                for (int i = 0; i < CurrentLevel.TileLayers.Length; i++)
                {
                    CurrentLevel.TileLayers[i].EditorDraw(spriteBatch, camera, emptyTile, drawGridToolStripMenuItem.Checked);

                    if (CurrentLevel.TileLayers[i] == selectedTileLayer)
                        break;
                }
            }
            else if (currentEditType == LayerType.Collision)
            {
                for (int i = 0; i < CurrentLevel.TileLayers.Length; i++)
                {
                    CurrentLevel.TileLayers[i].Draw(spriteBatch, camera);
                }

                CurrentLevel.CollisionLayer.EditorDraw(spriteBatch, camera, notWalkable);
            }
            else if (currentEditType == LayerType.Light)
            {
                GraphicsDevice.SetRenderTarget(0, colorMapRenderTarget);
                GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Microsoft.Xna.Framework.Graphics.Color.Black, 1, 0);

                for (int i = 0; i < CurrentLevel.TileLayers.Length; i++)
                {
                    CurrentLevel.TileLayers[i].Draw(spriteBatch, camera);
                }

                GraphicsDevice.SetRenderTarget(0, null);

                colorMapTexture = colorMapRenderTarget.GetTexture();
                shadowMapTexture = GetShadowMap();

                DrawCombinedMaps();
            }

            //Als de muis zich boven het level bevind, teken een doorzichtige tile op die plek
            DrawMouse();
        }

        private Texture2D GetShadowMap()
        {
            GraphicsDevice.SetRenderTarget(0, shadowMapRenderTarget);
            GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Microsoft.Xna.Framework.Graphics.Color.Black, 1, 0);

            GraphicsDevice.RenderState.AlphaBlendEnable = true;
            GraphicsDevice.RenderState.SourceBlend = Blend.One;
            GraphicsDevice.RenderState.DestinationBlend = Blend.One;

            foreach (var light in CurrentLevel.Lights)
            {
                if (!light.IsEnabled ||
                    light.Position.X + light.Radius < camera.Position.X ||
                    light.Position.Y + light.Radius < camera.Position.Y ||
                    light.Position.X - light.Radius > camera.Position.X + Camera2D.ScreenWidth ||
                    light.Position.Y - light.Radius > camera.Position.Y + Camera2D.ScreenHeight)
                    continue;

                lightEffect.CurrentTechnique = lightEffect.Techniques["PointLight"];
                lightEffect.Parameters["screenWidth"].SetValue(GraphicsDevice.Viewport.Width);
                lightEffect.Parameters["screenHeight"].SetValue(GraphicsDevice.Viewport.Height);

                lightEffect.Parameters["lightStrength"].SetValue(light.Strength);
                lightEffect.Parameters["lightRadius"].SetValue(light.Radius);
                lightEffect.Parameters["lightPosition"].SetValue(light.GetScreenPosition(camera));
                lightEffect.Parameters["lightColor"].SetValue(light.ColorV3);

                //lightEffect.Parameters["NormalMap"].SetValue();
                //lightEffect.Parameters["DepthMap"].SetValue();

                lightEffect.Begin();
                {
                    foreach (var pass in lightEffect.CurrentTechnique.Passes)
                    {
                        pass.Begin();
                        {
                            GraphicsDevice.VertexDeclaration = vertexDeclaration;
                            GraphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, vertices, 0, 2);
                        }
                        pass.End();
                    }
                }
                lightEffect.End();
            }

            GraphicsDevice.RenderState.AlphaBlendEnable = false;

            GraphicsDevice.SetRenderTarget(0, null);

            return shadowMapRenderTarget.GetTexture();
        }

        private void DrawCombinedMaps()
        {
            combinedEffect.CurrentTechnique = combinedEffect.Techniques["LightingCombined"];
            combinedEffect.Parameters["ambient"].SetValue(CurrentLevel.AmbientAlpha);
            combinedEffect.Parameters["ambientColor"].SetValue(CurrentLevel.AmbientColor.ToVector4());
            combinedEffect.Parameters["lightAmbient"].SetValue(Light.ambient);

            combinedEffect.Parameters["ColorMap"].SetValue(colorMapTexture);
            combinedEffect.Parameters["ShadowMap"].SetValue(shadowMapTexture);

            spriteBatch.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);
            {
                combinedEffect.Begin();
                {
                    foreach (var pass in combinedEffect.CurrentTechnique.Passes)
                    {
                        pass.Begin();
                        {
                            spriteBatch.Draw(colorMapTexture, Vector2.Zero, Microsoft.Xna.Framework.Graphics.Color.White);
                        }
                        pass.End();
                    }
                }
                combinedEffect.End();
            }
            spriteBatch.End();

            DrawLightNames();
        }

        private void DrawLightNames()
        {
            if (CurrentLevel == null || CurrentLevel.Lights.Count == 0)
                return;

            spriteBatch.Begin();
            foreach (Light light in CurrentLevel.Lights)
            {
                string text;
                if (light.Name == null)
                    text = "null";
                else
                    text = light.Name;

                spriteBatch.DrawString(arialFont, text, light.PositionV2 - camera.Position, Microsoft.Xna.Framework.Graphics.Color.Fuchsia);
            }
            spriteBatch.End();
        }

        private void DrawMouse()
        {
            if (cellX != -1 && cellY != -1 && Level.Tileset != null)
            {
                spriteBatch.Begin();
                {
                    if (currentEditType == LayerType.Tile)
                    {
                        spriteBatch.Draw(
                            Level.Tileset,
                            new Microsoft.Xna.Framework.Rectangle(
                                cellX * Level.TileDrawWidth - camera.IntX,
                                cellY * Level.TileDrawHeight - camera.IntY,
                                Level.TileDrawWidth,
                                Level.TileDrawHeight),
                            TileLayer.GetSourceRectangle(Level.Tileset.Width, tileSelector1.SelectedIndex),
                            new Microsoft.Xna.Framework.Graphics.Color(255, 255, 255, 150));
                        spriteBatch.Draw(
                            tileMarker,
                            new Microsoft.Xna.Framework.Rectangle(
                                cellX * Level.TileDrawWidth - camera.IntX,
                                cellY * Level.TileDrawHeight - camera.IntY,
                                Level.TileDrawWidth,
                                Level.TileDrawHeight),
                            Microsoft.Xna.Framework.Graphics.Color.White);
                    }
                    else if (currentEditType == LayerType.Collision)
                    {
                        spriteBatch.Draw(
                            notWalkable,
                            new Microsoft.Xna.Framework.Rectangle(
                                cellX * Level.TileDrawWidth - camera.IntX,
                                cellY * Level.TileDrawHeight - camera.IntY,
                                Level.TileDrawWidth,
                                Level.TileDrawHeight),
                            new Microsoft.Xna.Framework.Graphics.Color(255, 255, 255, 150));
                    }
                    else if (currentEditType == LayerType.Light)
                    {

                    }
                }
                spriteBatch.End();
            }
        }

        #region ToolStrip Level Buttons
        private void newLevelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            NewLevel();
        }

        private void openLevelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenLevel();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveLevel();
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveLevelAs();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void newLevelToolStripButton_Click(object sender, EventArgs e)
        {
            NewLevel();
        }

        private void openLevelToolStripButton_Click(object sender, EventArgs e)
        {
            OpenLevel();
        }

        private void saveLevelToolStripButton_Click(object sender, EventArgs e)
        {
            SaveLevel();
        }
        #endregion

        #region ToolStrip Tool Buttons
        private void paintBrushToolStripButton_Click(object sender, EventArgs e)
        {
            currentEditType = LayerType.Tile;

            if (!paintBrushToolStripButton.Checked)
            {
                toolState = ToolState.PaintBrush;

                UncheckAllToolStripButtons();

                paintBrushToolStripButton.Checked = true;
            }
        }

        private void paintBucketToolStripButton_Click(object sender, EventArgs e)
        {
            currentEditType = LayerType.Tile;

            if (!paintBucketToolStripButton.Checked)
            {
                toolState = ToolState.PaintBucket;

                UncheckAllToolStripButtons();

                paintBucketToolStripButton.Checked = true;
            }
        }

        private void eraserToolStripButton_Click(object sender, EventArgs e)
        {
            currentEditType = LayerType.Tile;

            if (!eraserToolStripButton.Checked)
            {
                toolState = ToolState.Eraser;

                UncheckAllToolStripButtons();

                eraserToolStripButton.Checked = true;
            }
        }

        private void collisionToolStripButton_Click(object sender, EventArgs e)
        {
            currentEditType = LayerType.Collision;

            if (!collisionToolStripButton.Checked)
            {
                toolState = ToolState.Collision;

                UncheckAllToolStripButtons();

                collisionToolStripButton.Checked = true;
            }
        }

        private void lightToolStripButton_Click(object sender, EventArgs e)
        {
            currentEditType = LayerType.Light;

            if (!lightToolStripButton.Checked)
            {
                toolState = ToolState.Light;

                UncheckAllToolStripButtons();

                lightToolStripButton.Checked = true;
            }
        }

        private void UncheckAllToolStripButtons()
        {
            paintBrushToolStripButton.Checked = false;
            paintBucketToolStripButton.Checked = false;
            eraserToolStripButton.Checked = false;
            collisionToolStripButton.Checked = false;
            lightToolStripButton.Checked = false;
        }
        #endregion

        #region Level Methods
        private void InitializeEditor(Level level)
        {
            this.Text = string.Format("{0} - Afterlife Level Editor", Path.GetFileNameWithoutExtension(Level.LevelPath));

            selectedTileLayer = level.TileLayers[0];
            for (int i = 0; i < level.TileLayers.Length; i++)
            {
                string tileLayerName = string.Format("TileLayer{0}", i);
                tileLayerDict.Add(tileLayerName, level.TileLayers[i]);
                tileLayersListBox.Items.Add(tileLayerName);
            }

            string collisionLayerName = "CollisionLayer";
            collisionLayerDict.Add(collisionLayerName, level.CollisionLayer);
            collisionLayersListBox.Items.Add(collisionLayerName);

            InitializeLightsTabPage(level);
        }

        //Maak een nieuw level aan
        private void NewLevel()
        {
            NewLevelForm form = new NewLevelForm();

            if (form.ShowDialog() == DialogResult.OK)
            {
                Level level = new Level(
                    int.Parse(form.widthTextBox.Text),
                    int.Parse(form.heightTextBox.Text));

                CurrentLevel = level;

                InitializeEditor(level);

                AdjustScrollBars();
            }
        }

        //Open een level
        private void OpenLevel()
        {
            OpenFileDialog dialog = new OpenFileDialog();

            dialog.Filter = AfterlifeLevelFileFilter;

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                CurrentLevel = Level.FromFile(GraphicsDevice, dialog.FileName);
                tileSelector1.SetTileSet(Image.FromFile(Level.EditorTilesetPath));
                Level.LevelPath = dialog.FileName;

                InitializeEditor(CurrentLevel);

                AdjustScrollBars();
            }
        }

        //Sla een level op
        private void SaveLevel()
        {
            if (CurrentLevel == null)
                return;

            if (string.IsNullOrEmpty(Level.LevelPath))
                SaveLevelAs();

            if (File.Exists(Level.LevelPath))
            {
                CurrentLevel.Save(Level.LevelPath, tilesetPathToolStripTextBox.Text);
            }
        }

        //Sla een level op als
        private void SaveLevelAs()
        {
            if (CurrentLevel == null)
                return;

            SaveFileDialog dialog = new SaveFileDialog();

            dialog.Filter = AfterlifeLevelFileFilter;

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                if (CurrentLevel == null)
                    return;

                CurrentLevel.Save(dialog.FileName, tilesetPathToolStripTextBox.Text);
                Level.LevelPath = dialog.FileName;
            }
        }
        #endregion

        //Laad een tileset
        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();

            dialog.Filter = ImageFilesFilter;

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                Image image = Image.FromFile(dialog.FileName);
                tileSelector1.SetTileSet(image);

                Level.Tileset = Texture2D.FromFile(GraphicsDevice, dialog.FileName);
                Level.EditorTilesetPath = dialog.FileName;
            }
        }

        //Pas de scrollBars aan als we de editor resizen
        private void Form1_Resize(object sender, EventArgs e)
        {
            AdjustRenderTargets();

            AdjustScrollBars();
        }

        private void levelDisplay_MouseDown(object sender, MouseEventArgs e)
        {
            mouseDown = true;
        }

        private void levelDisplay_MouseUp(object sender, MouseEventArgs e)
        {
            mouseDown = false;
        }

        //Vraag de gebruiken of hij de editor echt wil sluiten
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            switch (MessageBox.Show("Are you sure you want to exit the editor?", "Afterlife Level Editor", MessageBoxButtons.YesNoCancel))
            {
                case DialogResult.Yes:
                    e.Cancel = false;
                    break;
                case DialogResult.No:
                    e.Cancel = true;
                    break;
                case DialogResult.Cancel:
                    e.Cancel = true;
                    break;
            }
        }

        private void resizeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (CurrentLevel == null)
                return;

            ResizeForm form = new ResizeForm(CurrentLevel.WidthInTiles, CurrentLevel.HeightInTiles);

            if (form.ShowDialog() == DialogResult.OK)
            {
                if (int.Parse(form.sizeWidthTextBox.Text) != CurrentLevel.WidthInTiles || int.Parse(form.sizeHeightTextBox.Text) != CurrentLevel.HeightInTiles)
                {
                    int newWidth = int.Parse(form.sizeWidthTextBox.Text);
                    int newHeight = int.Parse(form.sizeHeightTextBox.Text);

                    CurrentLevel.Resize(newWidth, newHeight, -1);
                }
                else if (!string.IsNullOrEmpty(form.offsetWidthTextBox.Text) && !string.IsNullOrEmpty(form.offsetHeightTextBox.Text))
                {
                    int offsetX = int.Parse(form.offsetWidthTextBox.Text);
                    int offsetY = int.Parse(form.offsetHeightTextBox.Text);

                    CurrentLevel.ResizeOffset(offsetX, offsetY, -1);
                }
            }
        }

        #region Lights
        private void InitializeLightsTabPage(Level level)
        {
            lightsDict.Clear();

            for (int i = 0; i < level.Lights.Count; i++)
            {
                lightsDict.Add(level.Lights[i].Name, level.Lights[i]);
                lightsListBox.Items.Add(level.Lights[i].Name);
            }

            if (level.Lights != null && level.Lights.Count > 0)
            {
                lightsPropertyGrid.SelectedObject = level.Lights[0];
                selectedLight = level.Lights[0];
            }
        }

        private void UpdateLightsPage()
        {
            if (lightsListBox.SelectedItem == null)
                return;

            selectedLight = lightsDict[lightsListBox.SelectedItem as string];

            lightsPropertyGrid.SelectedObject = selectedLight;
            lightRadiusTrackBar.Value = (int)selectedLight.Radius;
        }

        private void lightsListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateLightsPage();
        }
        
        private void addLightButton_Click(object sender, EventArgs e)
        {
            AddLight(Vector2.Zero);
        }

        private void AddLight(Vector2 position)
        {
            if (CurrentLevel == null)
                return;

            string lightname = string.Format("Light{0}", CurrentLevel.Lights.Count);

            Light light = new Light(lightname, Microsoft.Xna.Framework.Graphics.Color.White, 30f, 30f, new Vector3(position.X, position.Y, 0));

            CurrentLevel.Lights.Add(light);
            lightsDict.Add(light.Name, light);
            lightsListBox.Items.Add(light.Name);

            UpdateLightsPage();
        }

        private void removeLightButton_Click(object sender, EventArgs e)
        {
            if (lightsListBox.SelectedItem == null)
                return;

            string lightname = lightsListBox.SelectedItem as string;
            Light selectedLight = lightsDict[lightname];
            lightsDict.Remove(lightname);
            CurrentLevel.Lights.Remove(selectedLight);
            lightsListBox.Items.Remove(lightname);
        }

        private void colorLightButton_Click(object sender, EventArgs e)
        {
            if (selectedLight == null)
                return;

            ColorDialog dialog = new ColorDialog();

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                selectedLight.Color = new Microsoft.Xna.Framework.Graphics.Color(
                    dialog.Color.R, 
                    dialog.Color.G, 
                    dialog.Color.B, 
                    dialog.Color.A);
            }
        }

        private void trackBar1_Scroll(object sender, EventArgs e)
        {
            if (selectedLight == null)
                return;

            selectedLight.Radius = lightRadiusTrackBar.Value;
        }
        #endregion

        private void zoomOutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Level.TileDrawWidth == MIN_TILEDRAWSIZE && Level.TileDrawHeight == MIN_TILEDRAWSIZE)
                return;

            Level.TileDrawWidth /= 2;
            Level.TileDrawHeight /= 2;

            AdjustScrollBars();
        }

        private void zoomInToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Level.TileDrawWidth == MAX_TILEDRAWSIZE && Level.TileDrawHeight == MAX_TILEDRAWSIZE)
                return;

            Level.TileDrawWidth *= 2;
            Level.TileDrawHeight *= 2;

            AdjustScrollBars();
        }

        private void gridToolStripMenuItem_Click(object sender, EventArgs e)
        {
            drawGridToolStripMenuItem.Checked = !drawGridToolStripMenuItem.Checked;
        }

        private void removeCollisionLayer_Click(object sender, EventArgs e)
        {

        }

        private void tileLayersListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            collisionLayersListBox.SelectedItem = null;
            selectedCollisionLayer = null;

            if(tileLayersListBox.SelectedItem != null)
                selectedTileLayer = tileLayerDict[tileLayersListBox.SelectedItem as string];
        }

        private void collisionLayersListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            tileLayersListBox.SelectedItem = null;
            selectedTileLayer = null;

            if(collisionLayersListBox.SelectedItem != null)
                selectedCollisionLayer = collisionLayerDict[collisionLayersListBox.SelectedItem as string];
        }
    }
}